/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gclient;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.util.StringTokenizer;

/**
 *
 * @author sajin
 */
public class Announcer implements Runnable {

	public Announcer(Socket clientSock, GalaxiaClientUI galaxiaClientUI) {
		announcerThread = new Thread(this, "Announcer_Thread");
		clientSocket = clientSock;
		this.galaxiaClientUI = galaxiaClientUI;
		announcerThread.start();
	}

	@Override
	public void run() {
		DataInputStream fromClient = null;
		DataOutputStream toClient = null;

		String userName;
		String sha1FileName;
		String filePath;
		int gid;

		try {
			fromClient = new DataInputStream(clientSocket.getInputStream());
			toClient = new DataOutputStream(clientSocket.getOutputStream());

			byte[] rqMsg = new byte[2048];
			fromClient.read(rqMsg);
			String rqMessage = new String(rqMsg);
			String replyMessage = new String();
			StringTokenizer st = new StringTokenizer(rqMessage, " ");
			switch (Integer.parseInt(st.nextToken())) {
				case 0:
					break;
				case 1:
					break;
				case 2:
					int subType = Integer.parseInt(st.nextToken());
					if (subType == 1) {
						// PUSH Message curresponing to invitation.
						String inviterUserName = st.nextToken();
						gid = Integer.parseInt(st.nextToken());

						if (galaxiaClientUI.confirmInvitation(inviterUserName, gid)) {
							replyMessage = "1 ";
                            galaxiaClientUI.addGroup(gid);
						} else {
							replyMessage = "0 ";
						}
						toClient.write(replyMessage.getBytes());
					} else if (subType == 4) {
						// Invitee accepted proposal.
						String inviteeUserName = st.nextToken();
						gid = Integer.parseInt(st.nextToken());
						galaxiaClientUI.showInvitationAccepted(inviteeUserName, gid);
					} else if (subType == 3) {
						// Invitee Rejected Proposal.
						String inviteeUserName = st.nextToken();
						gid = Integer.parseInt(st.nextToken());
						galaxiaClientUI.showInvitationRejected(inviteeUserName, gid);
					}
					break;
				case 10:
					// Request for availability of a file.
					//userName = st.nextToken();
					sha1FileName = st.nextToken();
					gid = Integer.parseInt(st.nextToken().trim());

					if (galaxiaClientUI.isFileAvailable(gid, sha1FileName) ) {
						if (galaxiaClientUI.isFullyAvailable(sha1FileName, gid)) {
							replyMessage =  "10 1 ";
						} else {
							replyMessage = "10 0 ";
							for( Integer chunk :  galaxiaClientUI.availableChunks(sha1FileName, gid) ) {
								replyMessage = replyMessage + chunk + " ";
							}
						}

						toClient.write(replyMessage.getBytes());
					}
					else {
						// This should not happen.
						// Ignore message.
					}

					break;
				case 11:
					// Request for a file chunk.
					userName = st.nextToken();
					sha1FileName = st.nextToken();
					int fileChunkSize = Integer.parseInt(st.nextToken().replace('N', ' ').trim());
					int fileChunkNumber = Integer.parseInt(st.nextToken().replace('N',' ').trim());
					gid = Integer.parseInt(st.nextToken().replace('N',' ').trim());

					filePath = galaxiaClientUI.getPath(sha1FileName, gid);

					toClient.write(FileTools.getChunk(filePath, fileChunkSize, fileChunkNumber));

					break;

				case 12:
					// Request for knowing number of chunks in a file.
					userName = st.nextToken();
					sha1FileName = st.nextToken();
					int chunkSize = Integer.parseInt(st.nextToken().replace('N', ' ' ).trim());
					gid = Integer.parseInt(st.nextToken().replace('N', ' ').trim());

                    

					filePath = galaxiaClientUI.getPath(sha1FileName, gid);

					replyMessage = Integer.toString(FileTools.nChunks(filePath, chunkSize)) + " ";

					toClient.write(replyMessage.getBytes());

					break;
				
				case 13:
					sha1FileName = st.nextToken();
					gid = Integer.parseInt(st.nextToken().trim());
					
					filePath = galaxiaClientUI.getPath(sha1FileName, gid);

					File file = new File(filePath);
					byte[] fileContents = new byte[(int)file.length()];

					toClient.write(fileContents);
					
					break;
				default:
					break;
			}

		} catch (IOException ex) {
			System.out.println("Error Occured :" + ex.getMessage());
		} finally {
			try {
				fromClient.close();
				toClient.close();
			} catch (IOException ex) {
				System.out.print(" Error Occured : " + ex.getMessage());
			}
		}

	}
	protected Thread announcerThread;
	protected Socket clientSocket;
	protected GalaxiaClientUI galaxiaClientUI;
}
